"""
音画同步功能模块
"""
from PyQt5.QtWidgets import (
    QWidget, QVBoxLayout, QHBoxLayout, QTableWidget, QTableWidgetItem, QHeaderView,
    QLabel, QMessageBox, QGroupBox, QGridLayout, QPushButton, QColorDialog, QInputDialog, QLineEdit, QDialog,
    QListWidget, QListWidgetItem, QCheckBox, QSlider
)
from PyQt5.QtCore import Qt, pyqtSignal, QEvent
from PyQt5.QtGui import QColor, QPixmap, QPainter
import os
import json

from app.ui.components.styled_button import StyledButton
from app.services.service_locator import ServiceLocator
from app.services.sync_service import ISyncService
from app.ui.windows.video_player_window import VideoPlayerWindow


class ColorButton(QPushButton):
    """
    颜色按钮类，显示当前选中的颜色
    """
    def __init__(self, color=None, parent=None):
        super().__init__(parent)
        # 设置与StyledButton一致的尺寸
        self.setFixedSize(80, 30)
        self.color = color or QColor(0, 255, 0)  # 默认绿色
        self.setStyleSheet(f"""
            QPushButton {{
                background-color: rgb({self.color.red()}, {self.color.green()}, {self.color.blue()});
                border: 1px solid #666;
                border-radius: 4px;
            }}
            QPushButton:hover {{
                border: 2px solid #333;
                border-radius: 4px;
            }}
        """)


class SyncModule(QWidget):
    """
    音画同步功能模块类，包含音画同步相关的UI和功能
    """
    
    # 定义信号
    sync_status_changed = pyqtSignal(bool)  # 音画同步状态变化信号
    background_color_changed = pyqtSignal(QColor)  # 背景颜色变化信号
    
    def __init__(self, parent=None):
        """
        初始化音画同步模块
        
        @param parent: 父组件
        """
        super().__init__(parent)
        
        # 初始化变量
        self.config_path = ""
        self.video_player_window = None
        self.background_color = QColor(0, 255, 0)  # 默认绿色
        self.volume = 50  # 默认音量为50%
        
        # 获取日志记录器
        from app.utils.logger import Logger
        self.logger = Logger.get_logger("sync_module")
        
        # 初始化UI
        self._init_ui()
        
        # 获取同步服务并添加事件监听
        self._setup_sync_service()
        
        # 不在初始化时加载假数据，等待设置配置路径后再加载真实数据
        
        # 监听模块显示事件
        self.installEventFilter(self)
    
    def eventFilter(self, obj, event):
        """
        事件过滤器，用于捕获模块显示事件
        
        @param obj: 事件对象
        @param event: 事件
        @return: 是否处理事件
        """
        # 当模块显示时自动刷新数据
        if obj == self and event.type() == QEvent.Show:
            self.logger.debug("音画同步模块显示，自动刷新数据")
            self._auto_refresh_data()
            
        return super().eventFilter(obj, event)
    
    def _auto_refresh_data(self):
        """
        自动刷新数据，不显示弹框提示
        """
        try:
            # 从配置服务获取配置路径
            from app.services.config_service import IConfigService
            config_service = ServiceLocator.get(IConfigService)
            
            if not config_service:
                self.logger.error("无法获取配置服务")
                return
                
            # 获取配置路径
            config_path = config_service.get("app.config_path", "")
            
            if not config_path:
                self.logger.warning("配置路径未设置，无法刷新数据")
                return
                
            # 更新模块的配置路径
            if self.config_path != config_path:
                self.logger.info(f"更新配置路径: {config_path}")
                self.config_path = config_path
            
            # 确保音画同步目录存在
            self._ensure_sync_directory()
            
            # 重新加载音画同步数据
            self._load_sync_data()
            
            self.logger.info("已自动刷新音画同步数据")
        except Exception as e:
            self.logger.error(f"自动刷新音画同步数据失败: {str(e)}")
            import traceback
            self.logger.error(traceback.format_exc())
    
    def _init_ui(self):
        """
        初始化UI
        """
        # 创建主布局
        self.layout = QVBoxLayout(self)
        self.layout.setContentsMargins(10, 10, 10, 10)
        self.layout.setSpacing(10)
        
        # 创建音画同步组
        self._create_sync_group(self.layout)
        
        # 不再单独创建颜色选择面板，而是将其集成到控制按钮区域
    
    def _create_sync_group(self, parent_layout):
        """
        创建音画同步组
        
        @param parent_layout: 父布局
        """
        # 创建音画同步表格
        self._create_sync_table()
        
        # 创建控制按钮
        self._create_control_buttons()
        
        # 添加到父布局
        parent_layout.addWidget(self.sync_table)
        parent_layout.addWidget(self.control_widget)
    
    def _create_sync_table(self):
        """
        创建音画同步表格
        """
        # 创建表格
        self.sync_table = QTableWidget(0, 3)
        self.sync_table.setHorizontalHeaderLabels(["视频", "话术", "关键词"])
        self.sync_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
        self.sync_table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
        self.sync_table.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch)
        self.sync_table.verticalHeader().setVisible(False)
        
        # 设置表格为只读模式
        self.sync_table.setEditTriggers(QTableWidget.NoEditTriggers)
        
        # 设置行高
        self.sync_table.verticalHeader().setDefaultSectionSize(28)
        
        # 连接双击事件
        self.sync_table.cellDoubleClicked.connect(self._on_cell_double_clicked)
        
        # 设置表格提示
        self.sync_table.setToolTip("双击视频列播放视频，双击话术列选择话术，双击关键词列编辑关键词")
        
        # 设置样式
        self.sync_table.setStyleSheet("""
            QTableWidget {
                border: 1px solid #ddd;
                border-radius: 3px;
                background-color: #fff;
                selection-background-color: #e6f3ff;
            }
            QTableWidget::item {
                padding: 4px;
                border-bottom: 1px solid #eee;
            }
            QHeaderView::section {
                background-color: #f5f5f5;
                padding: 4px;
                border: none;
                border-bottom: 1px solid #ddd;
                font-weight: bold;
            }
        """)
    
    def _create_control_buttons(self):
        """
        创建控制按钮
        """
        # 创建控制按钮容器
        self.control_widget = QWidget()
        control_layout = QHBoxLayout(self.control_widget)
        control_layout.setContentsMargins(0, 5, 0, 0)
        
        # 创建颜色选择按钮（放在左侧）
        self.color_button = ColorButton(self.background_color)
        self.color_button.clicked.connect(self._show_color_dialog)
        
        # 创建音量控制滑块
        volume_layout = QHBoxLayout()
        volume_layout.setContentsMargins(10, 0, 10, 0)
        
        # 添加音量图标标签
        volume_label = QLabel("🔊")
        volume_label.setToolTip("视频音量")
        
        # 创建音量滑块
        self.volume_slider = QSlider(Qt.Horizontal)
        self.volume_slider.setMinimum(0)
        self.volume_slider.setMaximum(100)
        self.volume_slider.setValue(self.volume)
        self.volume_slider.setFixedWidth(100)
        self.volume_slider.setToolTip(f"当前音量: {self.volume}%")
        self.volume_slider.valueChanged.connect(self._on_volume_changed)
        
        # 添加到音量布局
        volume_layout.addWidget(volume_label)
        volume_layout.addWidget(self.volume_slider)
        
        # 创建开启/关闭按钮
        self.sync_button = StyledButton("开启")
        self.sync_button.clicked.connect(self._on_sync_clicked)
        
        # 添加按钮到布局
        control_layout.addWidget(self.color_button)  # 左侧放置颜色按钮
        control_layout.addLayout(volume_layout)      # 添加音量控制
        control_layout.addStretch(1)                 # 添加弹性空间
        control_layout.addWidget(self.sync_button)   # 开启/关闭按钮
    
    def _on_sync_clicked(self):
        """
        处理开启/关闭按钮点击事件
        """
        # 获取当前按钮文本判断状态
        current_state = self.sync_button.text() == "关闭"
        # 切换状态
        new_state = not current_state
        
        # 更新按钮文本
        new_button_text = "关闭" if new_state else "开启"
        self.sync_button.setText(new_button_text)
        
        # 获取音画同步服务并设置状态
        sync_service = ServiceLocator.get(ISyncService)
        if sync_service:
            sync_service.enable_sync(new_state)
        
        # 处理视频播放窗口
        if new_state:
            self._show_video_player_window()
        else:
            self._hide_video_player_window()
        
        # 发送状态变化信号，更新状态栏
        self.sync_status_changed.emit(new_state)
        
        # 直接更新状态栏显示
        status_text = "已开启" if new_state else "未开启"
        # 查找主窗口并更新状态
        main_window = self.window()
        if hasattr(main_window, 'update_sync_status'):
            main_window.update_sync_status(status_text)
    
    def _setup_sync_service(self):
        """
        设置同步服务并添加事件监听
        """
        sync_service = ServiceLocator.get(ISyncService)
        if sync_service:
            # 添加play_video事件监听
            sync_service.add_listener("play_video", self._on_play_video)
    
    def _on_play_video(self, event):
        """
        处理播放视频事件
        
        @param event: 事件对象，包含视频路径
        """
        if hasattr(event, 'data') and 'video' in event.data:
            video_path = event.data['video']
            # 确保视频播放窗口已创建并显示
            if self._ensure_video_player_window():
                # 播放视频
                self.video_player_window.play_video(video_path)
    
    def _ensure_video_player_window(self):
        """
        确保视频播放窗口已创建
        
        @return: 是否成功创建视频播放窗口
        """
        try:
            # 如果视频播放窗口不存在，创建一个
            if not self.video_player_window:
                from app.ui.windows.video_player_window import VideoPlayerWindow
                self.video_player_window = VideoPlayerWindow()
                
                # 设置背景颜色
                self.video_player_window.set_background_color(self.background_color)
                
                # 连接视频拖放信号
                self.video_player_window.video_dropped.connect(self._on_video_dropped)
                
                # 设置初始音量
                self.video_player_window.media_player.setVolume(self.volume)
                
                self.logger.info("已创建视频播放窗口")
            
            return True
        except Exception as e:
            self.logger.error(f"创建视频播放窗口失败: {str(e)}")
            import traceback
            self.logger.error(traceback.format_exc())
            return False
    
    def _show_video_player_window(self):
        """
        显示视频播放窗口
        """
        if self._ensure_video_player_window():
            self.video_player_window.show()
    
    def _hide_video_player_window(self):
        """
        隐藏视频播放窗口
        """
        if self.video_player_window:
            self.video_player_window.hide()
            # 停止当前播放的视频
            self.video_player_window.stop_video()
    
    def _on_video_dropped(self, file_path):
        """
        处理视频拖放事件
        
        @param file_path: 视频文件路径
        """
        if not self.config_path:
            self.logger.warning("配置路径未设置，无法处理拖放视频")
            QMessageBox.warning(self, "警告", "配置路径未设置，请先在配置选项卡中设置配置路径")
            return
            
        try:
            # 获取视频文件名
            video_name = os.path.basename(file_path)
            
            # 音画同步目录
            sync_dir = os.path.join(self.config_path, "音画同步")
            if not os.path.exists(sync_dir):
                os.makedirs(sync_dir)
                self.logger.info(f"创建音画同步目录: {sync_dir}")
            
            # 目标视频路径
            target_video_path = os.path.join(sync_dir, video_name)
            
            # 检查是否已存在同名视频
            if os.path.exists(target_video_path) and os.path.normpath(file_path) != os.path.normpath(target_video_path):
                # 静默覆盖，不再弹出确认对话框
                self.logger.info(f"已存在同名视频文件 {video_name}，将覆盖")
            
            # 如果拖放的文件不在音画同步目录中，则复制到该目录
            if os.path.normpath(file_path) != os.path.normpath(target_video_path):
                import shutil
                shutil.copy2(file_path, target_video_path)
                self.logger.info(f"复制视频文件: {file_path} -> {target_video_path}")
            
            # 更新配置文件
            config_file = os.path.join(sync_dir, "config.json")
            config_data = []
            
            # 读取现有配置文件
            if os.path.exists(config_file):
                try:
                    with open(config_file, 'r', encoding='utf-8') as f:
                        config_data = json.load(f)
                except Exception as e:
                    self.logger.error(f"读取配置文件失败: {str(e)}")
                    import traceback
                    self.logger.error(traceback.format_exc())
            
            # 检查视频是否已在配置中
            video_exists = False
            for item in config_data:
                if item.get("video", "") == video_name:
                    video_exists = True
                    self.logger.info(f"视频 {video_name} 已存在于配置文件中")
                    break
            
            # 如果视频不在配置中，添加它
            if not video_exists:
                # 添加到配置数据，使用空话术和关键词列表
                config_data.append({
                    "video": video_name,
                    "text": [],  # 空话术列表
                    "keywords": []  # 空关键词列表
                })
                
                # 保存配置文件
                try:
                    with open(config_file, 'w', encoding='utf-8') as f:
                        json.dump(config_data, f, ensure_ascii=False, indent=2)
                    self.logger.info(f"已更新配置文件: {config_file}")
                except Exception as e:
                    self.logger.error(f"保存配置文件失败: {str(e)}")
                    import traceback
                    self.logger.error(traceback.format_exc())
            
            # 重新加载音画同步数据
            self._load_sync_data()
            
            # 不再显示提示弹框
            self.logger.info(f"已添加视频 {video_name}")
            
        except Exception as e:
            self.logger.error(f"处理拖放视频失败: {str(e)}")
            import traceback
            self.logger.error(traceback.format_exc())
            QMessageBox.critical(self, "错误", f"处理拖放视频失败: {str(e)}")
    
    def add_sync_item(self, speech, video, keyword):
        """
        添加音画同步项目
        
        @param speech: 话术
        @param video: 视频
        @param keyword: 关键词
        """
        # 添加到表格，注意列顺序已调整为：视频、话术、关键词
        row = self.sync_table.rowCount()
        self.sync_table.insertRow(row)
        
        # 创建视频单元格并添加视觉提示
        video_item = QTableWidgetItem(f"▶ {os.path.basename(video)}")
        video_item.setToolTip("双击播放视频")
        video_item.setForeground(QColor(0, 120, 215))
        self.sync_table.setItem(row, 0, video_item)
        
        # 添加话术和关键词单元格
        self.sync_table.setItem(row, 1, QTableWidgetItem(speech))
        self.sync_table.setItem(row, 2, QTableWidgetItem(keyword))
        
        self.sync_table.scrollToBottom()
        
        # 添加到音画同步服务
        sync_service = ServiceLocator.get(ISyncService)
        if sync_service:
            sync_service.add_sync_item(speech, video, keyword)
    
    def load_sync_items(self):
        """
        从服务加载音画同步项目
        """
        sync_service = ServiceLocator.get(ISyncService)
        if not sync_service:
            return
        
        # 清空表格
        self.sync_table.setRowCount(0)
        
        # 获取所有项目并添加到表格
        items = sync_service.get_sync_items()
        for speech, video, keyword in items:
            self.add_sync_item(speech, video, keyword)
        
        # 获取当前音画同步状态并更新状态栏
        is_enabled = sync_service.is_sync_enabled()
        status = "已开启" if is_enabled else "未开启"
        
        # 更新按钮状态
        self.update_sync_status(is_enabled)
        
        # 更新主窗口状态栏
        main_window = self.window()
        if hasattr(main_window, 'update_sync_status'):
            main_window.update_sync_status(status)
    
    def update_sync_status(self, enabled):
        """
        更新音画同步状态
        
        @param enabled: 是否启用
        """
        self.sync_button.setText("关闭" if enabled else "开启")
        
        # 处理视频播放窗口
        if enabled:
            self._show_video_player_window()
        else:
            self._hide_video_player_window()
    
    def set_config_path(self, path):
        """
        设置配置路径
        
        @param path: 配置路径
        """
        self.logger.info(f"设置配置路径: {path}")
        
        # 清空表格
        self.sync_table.setRowCount(0)
        
        # 设置新的配置路径
        self.config_path = path
        
        if not path:
            self.logger.warning("配置路径为空，不加载数据")
            return
            
        # 创建音画同步目录
        self._ensure_sync_directory()
        
        # 确保配置文件存在
        sync_dir = os.path.join(path, "音画同步")
        config_file = os.path.join(sync_dir, "config.json")
        
        # 如果配置文件不存在，创建空配置文件
        if not os.path.exists(config_file):
            try:
                with open(config_file, 'w', encoding='utf-8') as f:
                    json.dump([], f, ensure_ascii=False, indent=2)
                self.logger.info(f"创建空配置文件: {config_file}")
            except Exception as e:
                self.logger.error(f"创建配置文件失败: {str(e)}")
                import traceback
                self.logger.error(traceback.format_exc())
        
        # 更新同步服务的默认保存路径
        sync_service = ServiceLocator.get(ISyncService)
        if sync_service:
            sync_service.configure({"default_save_path": config_file})
            self.logger.info(f"已更新同步服务的默认保存路径: {config_file}")
        
        # 检查话术
        self._check_speeches()
        
        # 加载音画同步数据
        self._load_sync_data()
    
    def _ensure_sync_directory(self):
        """
        确保音画同步目录存在
        """
        if not self.config_path:
            self.logger.warning("配置路径为空，无法创建音画同步目录")
            return
            
        # 创建音画同步目录
        sync_dir = os.path.join(self.config_path, "音画同步")
        if not os.path.exists(sync_dir):
            try:
                os.makedirs(sync_dir)
                self.logger.info(f"创建音画同步目录: {sync_dir}")
            except Exception as e:
                self.logger.error(f"创建音画同步目录失败: {str(e)}")
                import traceback
                self.logger.error(traceback.format_exc())
        else:
            self.logger.info(f"音画同步目录已存在: {sync_dir}")
    
    def _load_sync_data(self):
        """
        加载音画同步数据
        1. 读取配置文件
        2. 获取实际视频列表
        3. 对比配置文件和实际视频文件
        4. 检查话术
        5. 更新配置文件和UI
        """
        if not self.config_path:
            # 如果没有配置路径，清空表格
            self.sync_table.setRowCount(0)
            self.logger.info("未设置配置路径，清空音画同步表格")
            return
            
        # 清空表格
        self.sync_table.setRowCount(0)
        
        # 音画同步目录
        sync_dir = os.path.join(self.config_path, "音画同步")
        if not os.path.exists(sync_dir):
            self.logger.info(f"音画同步目录不存在: {sync_dir}")
            return
            
        try:
            # 配置文件路径
            config_file = os.path.join(sync_dir, "config.json")
            
            # 获取同步服务
            sync_service = ServiceLocator.get(ISyncService)
            if not sync_service:
                self.logger.error("无法获取同步服务")
                return
            
            # 读取所有视频文件
            video_files = []
            for file in os.listdir(sync_dir):
                file_path = os.path.join(sync_dir, file)
                if os.path.isfile(file_path) and self._is_video_file(file_path):
                    video_files.append(file)  # 只保存文件名
            
            self.logger.info(f"在音画同步目录中找到 {len(video_files)} 个视频文件")
            
            # 读取配置文件
            config_data = []
            config_videos = []
            if os.path.exists(config_file):
                try:
                    with open(config_file, 'r', encoding='utf-8') as f:
                        config_data = json.load(f)
                        
                    # 获取配置文件中的视频列表
                    config_videos = [item.get("video", "") for item in config_data]
                    self.logger.info(f"从配置文件中读取到 {len(config_videos)} 个视频记录")
                except Exception as e:
                    self.logger.error(f"读取配置文件失败: {str(e)}")
                    import traceback
                    self.logger.error(traceback.format_exc())
            else:
                self.logger.info(f"配置文件不存在，将创建新文件: {config_file}")
            
            # 对比配置文件和实际视频文件
            has_changes = False
            
            # 检查新增的视频
            for video in video_files:
                if video not in config_videos:
                    self.logger.info(f"发现新增视频: {video}")
                    
                    # 添加到配置数据，使用空话术和关键词列表
                    config_data.append({
                        "video": video,
                        "text": [],
                        "keywords": []
                    })
                    
                    has_changes = True
            
            # 检查删除的视频
            for i in range(len(config_data) - 1, -1, -1):
                video = config_data[i].get("video", "")
                if video not in video_files:
                    self.logger.info(f"发现已删除视频: {video}")
                    config_data.pop(i)
                    has_changes = True
            
            # 如果有变更，保存配置文件
            if has_changes:
                try:
                    with open(config_file, 'w', encoding='utf-8') as f:
                        json.dump(config_data, f, ensure_ascii=False, indent=2)
                    self.logger.info(f"已更新配置文件: {config_file}")
                except Exception as e:
                    self.logger.error(f"保存配置文件失败: {str(e)}")
                    import traceback
                    self.logger.error(traceback.format_exc())
            
            # 检查话术
            self._check_speeches()
            
            # 清空同步服务中的项目
            sync_service.clear_sync_items()
            self.logger.info("已清空同步服务中的项目")
            
            # 加载数据到表格和服务
            items_added = 0
            for item in config_data:
                video_name = item.get("video", "")
                speech_list = item.get("text", [])
                keyword_list = item.get("keywords", [])
                
                # 检查视频文件是否存在
                video_path = os.path.join(sync_dir, video_name)
                if not os.path.exists(video_path):
                    self.logger.warning(f"视频文件不存在，跳过: {video_path}")
                    continue
                
                # 将话术列表和关键词列表转换为字符串
                speech_text = ", ".join(speech_list)
                keyword_text = ", ".join(keyword_list)
                
                # 添加到表格
                row = self.sync_table.rowCount()
                self.sync_table.insertRow(row)
                self.sync_table.setItem(row, 0, QTableWidgetItem(video_name))
                self.sync_table.setItem(row, 1, QTableWidgetItem(speech_text))
                self.sync_table.setItem(row, 2, QTableWidgetItem(keyword_text))
                
                # 添加到同步服务
                sync_service.add_sync_item(speech_text, video_path, keyword_text)
                
                # 在加载数据到表格后，为视频列添加视觉提示
                video_item = self.sync_table.item(row, 0)
                if video_item:
                    # 设置单元格提示
                    video_item.setToolTip("双击播放视频")
                    # 设置单元格文本前缀，添加播放图标提示
                    video_name = video_item.text()
                    video_item.setText(f"▶ {video_name}")
                    # 设置单元格文本颜色为蓝色，表示可点击
                    video_item.setForeground(QColor(0, 120, 215))
                
                items_added += 1
            
            self.logger.info(f"成功加载 {items_added} 个音画同步项目到表格")
            
            # 获取当前音画同步状态并更新状态栏
            # 注意：这里不要将项目数量作为状态传递给状态栏
            is_enabled = sync_service.is_sync_enabled()
            status = "已开启" if is_enabled else "未开启"
            
            # 更新按钮状态
            self.update_sync_status(is_enabled)
            
            # 更新主窗口状态栏
            main_window = self.window()
            if hasattr(main_window, 'update_sync_status'):
                main_window.update_sync_status(status)
            
        except Exception as e:
            self.logger.error(f"加载音画同步数据失败: {str(e)}")
            import traceback
            self.logger.error(traceback.format_exc())
    
    def _is_video_file(self, file_path):
        """
        检查文件是否是视频文件
        
        @param file_path: 文件路径
        @return: 是否是视频文件
        """
        video_extensions = ['.mp4', '.avi', '.mov', '.wmv', '.flv', '.mkv']
        _, ext = os.path.splitext(file_path.lower())
        is_video = ext in video_extensions
        
        if is_video:
            self.logger.debug(f"识别到视频文件: {file_path}")
        
        return is_video
    
    def closeEvent(self, event):
        """
        处理窗口关闭事件
        
        @param event: 关闭事件
        """
        # 关闭视频播放窗口
        if self.video_player_window:
            self.video_player_window.close()
            self.video_player_window = None
        
        # 接受关闭事件
        event.accept()
    
    def _show_color_dialog(self):
        """
        显示颜色选择对话框
        """
        # 打开颜色选择对话框
        color = QColorDialog.getColor(self.background_color, self, "选择背景颜色", 
                                     QColorDialog.ShowAlphaChannel)
        
        # 如果用户选择了颜色（没有点击取消）
        if color.isValid():
            # 更新当前颜色
            self.background_color = color
            
            # 更新颜色按钮样式
            self.color_button.color = color
            self.color_button.setStyleSheet(f"""
                QPushButton {{
                    background-color: rgb({color.red()}, {color.green()}, {color.blue()});
                    border: 1px solid #666;
                    border-radius: 4px;
                }}
                QPushButton:hover {{
                    border: 2px solid #333;
                    border-radius: 4px;
                }}
            """)
            
            # 如果视频播放窗口已创建，更新其背景颜色
            if self.video_player_window:
                self.video_player_window.set_background_color(color)
            
            # 发送颜色变化信号
            self.background_color_changed.emit(color) 
    
    def _on_cell_double_clicked(self, row, column):
        """
        处理单元格双击事件
        
        @param row: 行索引
        @param column: 列索引
        """
        # 处理关键词列（第2列，索引为2）的双击事件
        if column == 2:
            self._edit_keywords(row)
        # 处理话术列（第1列，索引为1）的双击事件
        elif column == 1:
            self._edit_speech(row)
        # 处理视频列（第0列，索引为0）的双击事件
        elif column == 0:
            self._play_video(row)
    
    def _edit_keywords(self, row):
        """
        编辑关键词
        
        @param row: 行索引
        """
        try:
            # 获取当前关键词
            current_keywords = self.sync_table.item(row, 2).text()
            self.logger.info(f"当前关键词: {current_keywords}")
            
            # 将逗号分隔的关键词转换为竖线分隔
            current_keywords_pipe = current_keywords.replace(", ", "|").replace(",", "|")
            self.logger.info(f"转换为竖线分隔的关键词: {current_keywords_pipe}")
            
            # 获取视频文件名
            video_name = self.sync_table.item(row, 0).text()
            
            # 创建输入对话框
            new_keywords, ok = QInputDialog.getText(
                self, 
                "编辑关键词", 
                f"请输入视频 '{video_name}' 的关键词，使用 | 分隔多个关键词：",
                QLineEdit.Normal,
                current_keywords_pipe
            )
            
            # 如果用户点击了确定按钮
            if ok:
                self.logger.info(f"用户输入的新关键词: {new_keywords}")
                
                # 将竖线分隔的关键词转换为逗号分隔
                new_keywords_comma = new_keywords.replace("|", ", ")
                self.logger.info(f"转换为逗号分隔的关键词: {new_keywords_comma}")
                
                # 更新表格中的关键词
                self.sync_table.item(row, 2).setText(new_keywords_comma)
                
                # 更新同步服务中的关键词
                self._update_keywords_in_service(row, new_keywords_comma)
                
                self.logger.info(f"已更新视频 '{video_name}' 的关键词: {new_keywords_comma}")
        except Exception as e:
            self.logger.error(f"编辑关键词失败: {str(e)}")
            import traceback
            self.logger.error(traceback.format_exc())
            QMessageBox.critical(self, "错误", f"编辑关键词失败: {str(e)}")
    
    def _update_keywords_in_service(self, row, new_keywords):
        """
        更新同步服务中的关键词和话术
        
        @param row: 行索引
        @param new_keywords: 新的关键词（逗号分隔）
        """
        try:
            # 获取同步服务
            sync_service = ServiceLocator.get(ISyncService)
            if not sync_service:
                self.logger.warning("无法获取同步服务")
                return
            
            # 获取视频和话术
            video = self.sync_table.item(row, 0).text()
            speech = self.sync_table.item(row, 1).text()
            
            # 如果视频名称带有播放图标前缀，去掉前缀
            if video.startswith("▶ "):
                video = video[2:].strip()
            
            # 音画同步目录
            sync_dir = os.path.join(self.config_path, "音画同步")
            video_path = os.path.join(sync_dir, video)
            
            # 检查视频文件是否存在
            if not os.path.exists(video_path):
                self.logger.warning(f"视频文件不存在: {video_path}")
                QMessageBox.warning(self, "警告", f"视频文件不存在: {video_path}")
                return
            
            # 移除旧项目
            sync_service.remove_sync_item(row)
            
            # 添加新项目
            sync_service.add_sync_item(speech, video_path, new_keywords)
            
            self.logger.info(f"已更新同步服务中的关键词: {new_keywords}")
            self.logger.info(f"已更新同步服务中的话术: {speech}")
            
            # 更新配置文件中的关键词和话术
            config_file = os.path.join(sync_dir, "config.json")
            if os.path.exists(config_file):
                try:
                    # 读取配置文件
                    with open(config_file, 'r', encoding='utf-8') as f:
                        config_data = json.load(f)
                    
                    # 查找对应的视频项
                    for item in config_data:
                        if item.get("video", "") == video:
                            # 将关键词字符串转换为列表
                            keyword_list = [k.strip() for k in new_keywords.split(',') if k.strip()]
                            # 更新关键词
                            item["keywords"] = keyword_list
                            
                            # 将话术字符串转换为列表，同时更新话术内容
                            speech_list = [s.strip() for s in speech.split(',') if s.strip()]
                            
                            # 获取可用的话术列表
                            available_speeches = self._get_available_speeches()
                            
                            # 过滤掉不存在的话术
                            if available_speeches:
                                speech_list = [s for s in speech_list if s in available_speeches]
                            
                            item["text"] = speech_list
                            
                            self.logger.info(f"已更新配置文件中的关键词: {keyword_list}")
                            self.logger.info(f"已更新配置文件中的话术: {speech_list}")
                            break
                    
                    # 保存配置文件
                    with open(config_file, 'w', encoding='utf-8') as f:
                        json.dump(config_data, f, ensure_ascii=False, indent=2)
                    
                    self.logger.info(f"已保存更新后的配置文件: {config_file}")
                except Exception as e:
                    self.logger.error(f"更新配置文件中的关键词和话术失败: {str(e)}")
                    import traceback
                    self.logger.error(traceback.format_exc())
            
        except Exception as e:
            self.logger.error(f"更新同步服务中的关键词和话术失败: {str(e)}")
            import traceback
            self.logger.error(traceback.format_exc())
            QMessageBox.critical(self, "错误", f"更新同步服务中的关键词和话术失败: {str(e)}")
    
    def _edit_speech(self, row):
        """
        编辑话术
        
        @param row: 行索引
        """
        try:
            # 获取当前话术
            current_speech_text = self.sync_table.item(row, 1).text()
            current_speeches = [s.strip() for s in current_speech_text.split(',') if s.strip()]
            self.logger.info(f"当前话术: {current_speeches}")
            
            # 获取视频文件名
            video_name = self.sync_table.item(row, 0).text()
            
            # 获取可用的话术列表
            available_speeches = self._get_available_speeches()
            if not available_speeches:
                QMessageBox.warning(self, "警告", "未找到可用的话术，请先在话术管理模块添加主话术")
                return
            
            # 创建多选对话框
            dialog = QDialog(self)
            dialog.setWindowTitle(f"选择话术 - {video_name}")
            dialog.setMinimumWidth(400)
            dialog.setMinimumHeight(300)
            
            layout = QVBoxLayout(dialog)
            
            # 添加说明标签
            label = QLabel("请勾选需要的话术：")
            layout.addWidget(label)
            
            # 创建列表部件
            list_widget = QListWidget()
            layout.addWidget(list_widget)
            
            # 添加话术项
            for speech in available_speeches:
                item = QListWidgetItem(speech)
                item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
                item.setCheckState(Qt.Checked if speech in current_speeches else Qt.Unchecked)
                list_widget.addItem(item)
            
            # 添加按钮
            button_layout = QHBoxLayout()
            ok_button = QPushButton("确定")
            cancel_button = QPushButton("取消")
            button_layout.addStretch()
            button_layout.addWidget(ok_button)
            button_layout.addWidget(cancel_button)
            layout.addLayout(button_layout)
            
            # 连接按钮信号
            ok_button.clicked.connect(dialog.accept)
            cancel_button.clicked.connect(dialog.reject)
            
            # 显示对话框
            if dialog.exec_() == QDialog.Accepted:
                # 获取选中的话术
                selected_speeches = []
                for i in range(list_widget.count()):
                    item = list_widget.item(i)
                    if item.checkState() == Qt.Checked:
                        selected_speeches.append(item.text())
                
                self.logger.info(f"用户选择的话术: {selected_speeches}")
                
                # 将话术列表转换为逗号分隔的字符串
                new_speech_text = ", ".join(selected_speeches)
                
                # 更新表格中的话术
                self.sync_table.item(row, 1).setText(new_speech_text)
                
                # 获取当前关键词
                current_keywords = self.sync_table.item(row, 2).text()
                
                # 更新同步服务中的话术和关键词
                self._update_keywords_in_service(row, current_keywords)
                
                self.logger.info(f"已更新视频 '{video_name}' 的话术: {new_speech_text}")
                
        except Exception as e:
            self.logger.error(f"编辑话术失败: {str(e)}")
            import traceback
            self.logger.error(traceback.format_exc())
            QMessageBox.critical(self, "错误", f"编辑话术失败: {str(e)}")

    def _get_available_speeches(self):
        """
        获取可用的话术列表
        
        @return: 话术名称列表
        """
        try:
            # 话术目录
            speech_dir = os.path.join(self.config_path, "话术管理", "主话术")
            if not os.path.exists(speech_dir):
                self.logger.warning(f"话术目录不存在: {speech_dir}")
                return []
            
            # 获取所有话术文件
            speech_files = []
            for file in os.listdir(speech_dir):
                file_path = os.path.join(speech_dir, file)
                if os.path.isfile(file_path) and file.endswith('.txt'):
                    # 去掉.txt后缀
                    speech_name = os.path.splitext(file)[0]
                    speech_files.append(speech_name)
            
            self.logger.info(f"找到 {len(speech_files)} 个可用话术")
            return speech_files
        
        except Exception as e:
            self.logger.error(f"获取话术列表失败: {str(e)}")
            import traceback
            self.logger.error(traceback.format_exc())
            return []

    def _check_speeches(self):
        """
        检查保存的话术是否存在
        """
        try:
            # 获取可用的话术列表
            available_speeches = self._get_available_speeches()
            if not available_speeches:
                self.logger.warning("未找到可用的话术")
                return
            
            # 音画同步目录
            sync_dir = os.path.join(self.config_path, "音画同步")
            if not os.path.exists(sync_dir):
                self.logger.warning(f"音画同步目录不存在: {sync_dir}")
                return
            
            # 配置文件路径
            config_file = os.path.join(sync_dir, "config.json")
            if not os.path.exists(config_file):
                self.logger.warning(f"配置文件不存在: {config_file}")
                return
            
            # 读取配置文件
            with open(config_file, 'r', encoding='utf-8') as f:
                config_data = json.load(f)
            
            # 检查每个视频的话术
            has_changes = False
            for item in config_data:
                speech_list = item.get("text", [])
                # 过滤掉不存在的话术
                new_speech_list = [speech for speech in speech_list if speech in available_speeches]
                
                # 如果有话术被移除，更新配置
                if len(new_speech_list) != len(speech_list):
                    self.logger.info(f"视频 {item.get('video', '')} 的话术有变更，原话术: {speech_list}, 新话术: {new_speech_list}")
                    item["text"] = new_speech_list
                    has_changes = True
                
            # 如果有变更，保存配置文件
            if has_changes:
                with open(config_file, 'w', encoding='utf-8') as f:
                    json.dump(config_data, f, ensure_ascii=False, indent=2)
                self.logger.info(f"已更新配置文件: {config_file}")
            
        except Exception as e:
            self.logger.error(f"检查话术失败: {str(e)}")
            import traceback
            self.logger.error(traceback.format_exc())

    def _play_video(self, row):
        """
        播放指定行的视频
        
        @param row: 行索引
        """
        try:
            # 检查音画同步功能是否开启
            if self.sync_button.text() != "关闭":
                self.logger.warning("音画同步功能未开启，无法播放视频")
                QMessageBox.information(self, "提示", "请先点击\"开启\"按钮启用音画同步功能后再播放视频")
                return
                
            # 获取视频文件名
            video_name = self.sync_table.item(row, 0).text()
            
            # 如果视频名称带有播放图标前缀，去掉前缀
            if video_name.startswith("▶ "):
                video_name = video_name[2:].strip()
            
            # 音画同步目录
            sync_dir = os.path.join(self.config_path, "音画同步")
            
            # 视频完整路径
            video_path = os.path.join(sync_dir, video_name)
            
            # 检查视频文件是否存在
            if not os.path.exists(video_path):
                self.logger.warning(f"视频文件不存在: {video_path}")
                QMessageBox.warning(self, "警告", f"视频文件不存在: {video_path}")
                return
            
            # 确保视频播放窗口已创建并显示
            if self._ensure_video_player_window():
                # 显示视频播放窗口
                self._show_video_player_window()
                
                # 播放视频
                self.video_player_window.play_video(video_path)
                
                self.logger.info(f"播放视频: {video_path}")
            else:
                self.logger.error("无法创建视频播放窗口")
                QMessageBox.critical(self, "错误", "无法创建视频播放窗口")
                
        except Exception as e:
            self.logger.error(f"播放视频失败: {str(e)}")
            import traceback
            self.logger.error(traceback.format_exc())
            QMessageBox.critical(self, "错误", f"播放视频失败: {str(e)}")

    def _on_volume_changed(self, value):
        """
        处理音量滑块值变化
        
        @param value: 新的音量值
        """
        self.volume = value
        self.volume_slider.setToolTip(f"当前音量: {value}%")
        
        # 如果视频播放窗口存在，更新其音量
        if self.video_player_window:
            self.video_player_window.media_player.setVolume(value)
            self.logger.info(f"视频音量已调整为: {value}%")